DATA_BLOCK DB 1
STRUCT
	Value		: INT;
	VAR0		: INT;
END_STRUCT;
BEGIN
	Value		:= 8290;
	VAR0		:= 0;
END_DATA_BLOCK


FUNCTION_BLOCK FB 1
BEGIN
	__ASSERT==	__AR 2,		P#42.0 // Check AR2 magic

	L		W#16#4321
	T		MW 0
END_FUNCTION_BLOCK


FUNCTION FC 1 : VOID
BEGIN
	__ASSERT==	__AR 2,		P#42.0 // Check AR2 magic

	L		W#16#1234
	T		MW 0
	CALL		FC 2
END_FUNCTION


FUNCTION FC 2 : VOID
BEGIN
	__ASSERT==	__AR 2,		P#42.0 // Check AR2 magic

	L		W#16#6789
	T		MW 0
	L		10
	T		LB 0
END_FUNCTION


FUNCTION FC 3 : VOID
BEGIN
	__ASSERT==	__AR 2,		P#42.0 // Check AR2 magic

	L		1
	T		LB 0
	CALL		FC 2
	__ASSERT==	LB 0,	1
END_FUNCTION


FUNCTION FC 4 : VOID
VAR_INPUT
	INPVAR		: INT;
	INPVAR3		: BOOL;
	INPVAR4		: BOOL;
END_VAR
VAR_IN_OUT
	INOUT0		: INT;
	INOUT1		: INT;
END_VAR
BEGIN
	__ASSERT==	__AR 2,		P#42.0 // Check AR2 magic

	// Check interface
	L		#INPVAR
	__ASSERT==	__ACCU 1,	9976
	U		#INPVAR3
	__ASSERT==	__STW VKE,	0
	U		#INPVAR4
	__ASSERT==	__STW VKE,	1
	L		#INOUT0
	__ASSERT==	__ACCU 1,	84
	L		#INOUT1
	__ASSERT==	__ACCU 1,	984

	L		42
	T		#INOUT0
	L		942
	T		#INOUT1
END_FUNCTION


FUNCTION FC 5 : VOID
VAR_INPUT
	INPVAR2		: INT;
	INPVAR3		: BOOL;
	INPVAR4		: BOOL;
END_VAR
VAR_IN_OUT
	INOUT0		: INT;
	INOUT1		: INT;
END_VAR
BEGIN
	__ASSERT==	__AR 2,		P#42.0 // Check AR2 magic

	// Check interface
	L		#INOUT0
	__ASSERT==	__ACCU 1,	84
	L		#INOUT1
	__ASSERT==	__ACCU 1,	984

	CALL FC 4 (
		INPVAR		:= #INPVAR2,	// This is a parameter
		INPVAR3		:= #INPVAR3,
		INPVAR4		:= #INPVAR4,
		INOUT0		:= #INOUT0,
		INOUT1		:= #INOUT1,
	)

	L		#INOUT0
	__ASSERT==	__ACCU 1,	42
	L		168
	T		#INOUT0
	L		#INOUT1
	__ASSERT==	__ACCU 1,	942
	L		9168
	T		#INOUT1
END_FUNCTION


FUNCTION FC 6 : VOID
BEGIN
	__ASSERT==	__AR 2,		P#42.0 // Check AR2 magic

	// Only check OV and OS bits
	__ASSERT==	__STW OV,	1
	__ASSERT==	__STW OS,	0
	L		1
	L		1
	+I
	__ASSERT==	__STW OV,	0
	__ASSERT==	__STW OS,	0
END_FUNCTION


FUNCTION FC 7 : VOID
BEGIN
	__ASSERT==	__AR 2,		P#42.0 // Check AR2 magic

	// Trigger an overflow
	__ASSERT==	__STW OV,	0
	__ASSERT==	__STW OS,	0
	L		30000
	L		30000
	+I
	__ASSERT==	__STW OV,	1
	__ASSERT==	__STW OS,	1
END_FUNCTION


FUNCTION_BLOCK FB 10
VAR_INPUT
	INVAR1		: BOOL;
	INVAR2		: BYTE;
	INVAR3		: WORD;
	INVAR4		: DWORD;
	INVAR5		: INT;
	INVAR6		: DINT;
	INVAR7		: REAL;
	INVAR8		: S5TIME;
	INVAR9		: TIME;
	INVAR10		: DATE;
	INVAR11		: CHAR;
END_VAR
VAR_OUTPUT
	RETURNVALUE	: INT;
END_VAR
BEGIN
	// This FB is CALLed. Check multi instance base register addresse.
	__ASSERT==	__AR 2,		P#DBX 0.0

	// Check parameter values
	U		#INVAR1
	__ASSERT==	__STW VKE,	1
	L		#INVAR2
	__ASSERT==	__ACCU 1,	B#16#12
	L		#INVAR3
	__ASSERT==	__ACCU 1,	W#16#3456
	L		#INVAR4
	__ASSERT==	__ACCU 1,	DW#16#88776655
	L		#INVAR5
	__ASSERT==	__ACCU 1,	8290
	L		#INVAR6
	__ASSERT==	__ACCU 1,	L#999999
	L		#INVAR7
	__ASSERT==	__ACCU 1,	9.876
	L		#INVAR8
	__ASSERT==	__ACCU 1,	S5T#9s
	L		#INVAR9
	__ASSERT==	__ACCU 1,	T#9s
	L		#INVAR10
	__ASSERT==	__ACCU 1,	900
	L		#INVAR11
	__ASSERT==	__ACCU 1,	'c'
	CALL FC 10 (
		INPUTVAR1	:= #INVAR1,
		INPUTVAR2	:= #INVAR2,
		INPUTVAR3	:= #INVAR3,
		INPUTVAR4	:= #INVAR4,
		INPUTVAR5	:= #INVAR5,
		INPUTVAR6	:= #INVAR6,
		INPUTVAR7	:= #INVAR7,
		INPUTVAR8	:= #INVAR8,
		INPUTVAR9	:= #INVAR9,
		INPUTVAR10	:= #INVAR10,
		INPUTVAR11	:= #INVAR11,
		INVAR_DB	:= DB1.DBW 0,
		RET_VAL		:= #RETURNVALUE,
	)

	// AR2 should still be the multi-instance base register, even if it
	// was clobbered in a called FC/FB.
	__ASSERT==	__AR 2,		P#DBX 0.0
END_FUNCTION_BLOCK


DATA_BLOCK DB 10
FB 10
BEGIN
END_DATA_BLOCK


FUNCTION FC 10 : INT
VAR_INPUT
	INPUTVAR1	: BOOL;
	INPUTVAR2	: BYTE;
	INPUTVAR3	: WORD;
	INPUTVAR4	: DWORD;
	INPUTVAR5	: INT;
	INPUTVAR6	: DINT;
	INPUTVAR7	: REAL;
	INPUTVAR8	: S5TIME;
	INPUTVAR9	: TIME;
	INPUTVAR10	: DATE;
	INPUTVAR11	: CHAR;
	INVAR_DB	: INT;
END_VAR
BEGIN
	// This FC is called from an FB. Thus it has the multi-instance base in AR2.
	__ASSERT==	__AR 2,		P#DBX 0.0

	// Check parameter values
	U		#INPUTVAR1
	__ASSERT==	__STW VKE,	1
	L		#INPUTVAR2
	__ASSERT==	__ACCU 1,	B#16#12
	L		#INPUTVAR3
	__ASSERT==	__ACCU 1,	W#16#3456
	L		#INPUTVAR4
	__ASSERT==	__ACCU 1,	DW#16#88776655
	L		#INPUTVAR5
	__ASSERT==	__ACCU 1,	8290
	L		#INPUTVAR6
	__ASSERT==	__ACCU 1,	L#999999
	L		#INPUTVAR7
	__ASSERT==	__ACCU 1,	9.876
	L		#INPUTVAR8
	__ASSERT==	__ACCU 1,	S5T#9s
	L		#INPUTVAR9
	__ASSERT==	__ACCU 1,	T#9s
	L		#INPUTVAR10
	__ASSERT==	__ACCU 1,	900
	L		#INPUTVAR11
	__ASSERT==	__ACCU 1,	'c'

	L		#INVAR_DB
	__ASSERT==	__ACCU 1,	8290


	// Check parameter pointers
	L		P##INPUTVAR1
	UD		DW#16#FFF80000
	__ASSERT==	__ACCU 1,	DW#16#87000000
	L		P##INPUTVAR2
	UD		DW#16#FFF80000
	__ASSERT==	__ACCU 1,	DW#16#87000000
	L		P##INPUTVAR3
	UD		DW#16#FFF80000
	__ASSERT==	__ACCU 1,	DW#16#87000000
	L		P##INPUTVAR4
	UD		DW#16#FFF80000
	__ASSERT==	__ACCU 1,	DW#16#87000000
	L		P##INPUTVAR5
	UD		DW#16#FFF80000
	__ASSERT==	__ACCU 1,	DW#16#87000000
	L		P##INPUTVAR6
	UD		DW#16#FFF80000
	__ASSERT==	__ACCU 1,	DW#16#87000000
	L		P##INPUTVAR7
	UD		DW#16#FFF80000
	__ASSERT==	__ACCU 1,	DW#16#87000000
	L		P##INPUTVAR8
	UD		DW#16#FFF80000
	__ASSERT==	__ACCU 1,	DW#16#87000000
	L		P##INPUTVAR9
	UD		DW#16#FFF80000
	__ASSERT==	__ACCU 1,	DW#16#87000000
	L		P##INPUTVAR10
	UD		DW#16#FFF80000
	__ASSERT==	__ACCU 1,	DW#16#87000000
	L		P##INPUTVAR11
	UD		DW#16#FFF80000
	__ASSERT==	__ACCU 1,	DW#16#87000000


	// Handle and check return value
	L		99
	T		#RET_VAL
	L		#RET_VAL
	__ASSERT==	__ACCU 1,	99
	L		P##RET_VAL
	UD		DW#16#FFF80000
	__ASSERT==	__ACCU 1,	DW#16#87000000


	// And another nested call
	CALL FC 11 (
		IN1	:= #INVAR_DB,
	)

	// Clobber the multi-instance base
	LAR2		P#84.0
END_FUNCTION


FUNCTION FC 11 : VOID
VAR_INPUT
	IN1		: INT;
END_VAR
BEGIN
	// This FC is called from an FB via FC. Thus it has the multi-instance base in AR2.
	__ASSERT==	__AR 2,		P#DBX 0.0

	L		#IN1
	__ASSERT==	__ACCU 1,	8290
END_FUNCTION


ORGANIZATION_BLOCK OB 1
BEGIN
	LAR2		P#42.0	// Magic AR2 value


	CALL		FC 1
	__ASSERT==	MW 0,	W#16#6789
	L		0
	T		MW 0
	__ASSERT==	MW 0,	0
	UC		FC 1
	__ASSERT==	MW 0,	W#16#6789
	L		0
	T		MW 0
	__ASSERT==	MW 0,	0
	SET
	CC		FC 1
	__ASSERT==	MW 0,	W#16#6789
	L		0
	T		MW 0
	__ASSERT==	MW 0,	0
	CLR
	CC		FC 1
	__ASSERT==	MW 0,	0

	__ASSERT==	__AR 2,		P#42.0 // Check AR2 magic

	// Test localdata stack
	L		255
	T		LB 0
	__ASSERT==	LB 0,	255
	CALL		FC 3
	__ASSERT==	LB 0,	255

	__ASSERT==	__AR 2,		P#42.0 // Check AR2 magic


	// Test nested FC calls
	L		84
	T		MW 42
	L		984
	T		DB1.DBW 2
	CALL FC 5 (
		INPVAR2		:= 9976,
		INPVAR3		:= FALSE,
		INPVAR4		:= TRUE,
		INOUT0		:= MW 42,
		INOUT1		:= DB1.DBW 2, // DB1.VAR0
	)
	L		MW 42
	__ASSERT==	__ACCU 1,	168
	L		DB1.DBW 2
	__ASSERT==	__ACCU 1,	9168

	__ASSERT==	__AR 2,		P#42.0 // Check AR2 magic


	// Test OV/OS bits over call boundaries
	__STWRST
	L		30000
	L		30000
	+I
	__ASSERT==	__STW OV,	1
	__ASSERT==	__STW OS,	1
	CALL FC 6
	__ASSERT==	__STW OV,	0
	__ASSERT==	__STW OS,	0
	__STWRST
	CALL FC 7
	__ASSERT==	__STW OV,	1
	__ASSERT==	__STW OS,	0

	__ASSERT==	__AR 2,		P#42.0 // Check AR2 magic


	// Test raw FB call
	L		0
	T		MW 0
	CLR
	UC		FB 1
	L		MW 0
	__ASSERT==	__ACCU 1,	W#16#4321
	L		0
	T		MW 0
	SET
	CC		FB 1
	L		MW 0
	__ASSERT==	__ACCU 1,	W#16#4321

	__ASSERT==	__AR 2,		P#42.0 // Check AR2 magic


	// Test indirect calls
	L		0
	T		MW 0
	L		1
	T		MW 50
	CLR
	UC		FC [MW 50]
	L		MW 0
	__ASSERT==	__ACCU 1,	W#16#6789
	L		0
	T		MW 0
	SET
	CC		FC [MW 50]
	L		MW 0
	__ASSERT==	__ACCU 1,	W#16#6789
	L		0
	T		MW 0
	CLR
	UC		FB [MW 50]
	L		MW 0
	__ASSERT==	__ACCU 1,	W#16#4321
	L		0
	T		MW 0
	SET
	CC		FB [MW 50]
	L		MW 0
	__ASSERT==	__ACCU 1,	W#16#4321

	__ASSERT==	__AR 2,		P#42.0 // Check AR2 magic


	// Test parameter forwarding (FB->FC)
	L		900
	T		MW 10
	CALL FB 10, DB 10 (
		INVAR1		:= TRUE,
		INVAR2		:= B#16#12,
		INVAR3		:= W#16#3456,
		INVAR4		:= DW#16#88776655,
		INVAR5		:= DB1.DBW 0,
		INVAR6		:= L#999999,
		INVAR7		:= 9.876,
		INVAR8		:= S5T#9s,
		INVAR9		:= T#9s,
		INVAR10		:= MW 10,
		INVAR11		:= 'c',
		RETURNVALUE	:= MW 0,
	)
	L		MW 0
	__ASSERT==	__ACCU 1,	99

	__ASSERT==	__AR 2,		P#42.0 // Check AR2 magic


	CALL SFC 46 // STOP CPU
END_ORGANIZATION_BLOCK
